﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestByWire.Tutorial.Domain;

namespace TestByWire.Tutorial
{
    [TestClass]
    [UseStub(typeof(IDataLayer), typeof(StubbedDataLayer))]
    public class UsingFakes : TestTarget<LogicLayer>
    {
        [TestMethod]
        public void MustBeAbleToUseFake()
        {
            Given.Fake<IDataLayer>(new FakedDataLayer());

            var result = When.Calling.Execute();

            Assert.AreEqual(FakedDataLayer.UniqueValue, result);
        }

        [TestMethod]
        public void FakeMustBeChosenOverStub()
        {
            Given.Fake<IDataLayer>(new FakedDataLayer("12345"));

            var result = When.Calling.Execute();

            Assert.AreEqual("12345", result);
        }

        [TestMethod]
        public void StubMustBeUsedIfNoFakeIsSpecified()
        {
            var result = When.Calling.Execute();

            Assert.AreEqual(StubbedDataLayer.UniqueValue, result);
        }

		[TestMethod]
		public void ValueMustBeLateBoundFaked()
		{
			Given.FakeLateBound("_theValue", 10);

			Assert.AreEqual(10, When.Calling.GetValue());
		}
    }

    public class FakedDataLayer : IDataLayer
    {
        private readonly string _theValue;
        public const string UniqueValue = "{6A25B72D-D716-4431-AFE6-CC9DA896D375}";

        public FakedDataLayer()
        {
            _theValue = UniqueValue;
        }

        public FakedDataLayer(string theValue)
        {
            _theValue = theValue;
        }

        public string Execute()
        {
            return _theValue;
        }

        public string[] ArrayExecute()
        {
            throw new NotImplementedException();
        }
    }

    public class StubbedDataLayer : IDataLayer
    {
        public const string UniqueValue = "{F5E6ACBD-B65D-4D05-BA2B-492E4C069BAF}";

        public string Execute()
        {
            return UniqueValue;
        }

        public string[] ArrayExecute()
        {
            throw new NotImplementedException();
        }
    }
}
